package it.crudity.core.dao;

import it.crudity.core.model.BaseEntity;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/***
 * 
 * @author g.caporaletti
 * 
 *         Generic Dao interface. Specific daos can implement interfaces that
 *         extend this.
 * 
 * @param <T>
 *            Entity Type
 * @param <ID>
 *            Entity Id Type
 */
public interface GenericDao<T extends BaseEntity<ID>, ID extends Serializable> {

	public static enum StringMatchMode {
		START, END, ANYWHERE, EXACT
	}

	/***
	 * 
	 * @param id
	 *            Entity id
	 * @return Object having the given id.
	 */
	public T get(ID id);

	/**
	 * @param id
	 *            Entity id
	 * @return Object to use only for association
	 */
	public T getForAssociation(ID id);

	/***
	 * Saves the given entity
	 * 
	 * @param object
	 *            Entity to save
	 */
	public void saveOrUpdate(T object);

	/***
	 * Deletes the given entity
	 * 
	 * @param object
	 *            Entity to delete
	 */
	public void delete(T object);

	/***
	 * Gets all the entities of type T
	 * 
	 * @return
	 */
	public List<T> getAll();

	/***
	 * Finds entites having a given property
	 * 
	 * @param property
	 *            Property name
	 * @param value
	 *            Property value
	 * @return {@link List} of matching entities.
	 */
	public List<T> findByProperty(String property, Object value);

	/***
	 * Finds entities having a property in a range of values
	 * 
	 * @param property
	 *            Property name
	 * @param values
	 *            {@link Collection} of possibile property values
	 * @return {@link List} of matching entities
	 */
	public List<T> findByPropertyIn(String property, Collection<? extends Object> values);

	public List<T> findAscendingOrderedByProperty(String property, Object value, String... orderingFields);

	/***
	 * Find entities having a string property match a value
	 * 
	 * @param property
	 *            Property name
	 * @param value
	 *            match
	 * @param matchMode
	 *            Match mode
	 * @return {@link List} of matching entities
	 */
	public List<T> findByStringPropertyLike(String property, String value, StringMatchMode matchMode);

	/***
	 * Finds entities having a property list match a series of values.
	 * 
	 * @param properties
	 *            Property names
	 * @param values
	 *            Property values
	 * @return {@link List} of matching entities
	 */
	public List<T> findByProperties(String[] properties, Object[] values);

	/***
	 * Finds entities having a list of string properties match a series of
	 * values.
	 * 
	 * @param properties
	 *            Property names
	 * @param values
	 *            Property values
	 * @param matchModes
	 *            Match mode
	 * @return {@link List} of matching entities
	 */
	public List<T> findByStringPropertiesLike(String[] properties, String[] values, StringMatchMode[] matchModes);

	/***
	 * Finds entities matching the property of a prototype object
	 * 
	 * @param example
	 *            The prototype object
	 * @return {@link List} of matching entities
	 */
	public List<T> findByExample(T example);

	/***
	 * Mark the entity as transient (i.e. not handled by persitence mechanisms)
	 * 
	 * @param entity
	 *            the entity to make transient
	 */
	public void makeTransient(T entity);

	/***
	 * 
	 * @return The entity {@link Class} for which this dao is responsible.
	 */
	public Class<T> getDomainModelObjectClass();

	/***
	 * 
	 * @return {@link Class} of the entity for which this dao is responsible.
	 */
	public Class<ID> getIdClass();

}
